/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.gitee.l0km.common.spring.core.annotation;

import java.lang.annotation.Annotation;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.Map.Entry;
import java.util.Set;
import com.gitee.l0km.common.spring.core.annotation.MergedAnnotation.Adapt;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;

public abstract class MergedAnnotationCollectors {

	private MergedAnnotationCollectors() {
	}


	@SuppressWarnings("rawtypes")
	private static final Function<MergedAnnotation, Annotation> MERGEDANNOTATION_FUN = new  Function<MergedAnnotation, Annotation>(){

		@Override
		public Annotation apply(MergedAnnotation input) {
			return input.synthesize();
		}

	};
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static <A extends Annotation> Set<A> toAnnotationSet(Iterable input, Predicate  filter, Comparator comprator) {
		if(null != filter) {
			input = FluentIterable.from(input).filter(filter);
		}
		if(null != comprator) {
			input = FluentIterable.from(input).toSortedList(comprator);
		}
		return (Set<A>) FluentIterable.from(input).transform(MERGEDANNOTATION_FUN).copyInto(new LinkedHashSet());
	}
	public static <A extends Annotation> Multimap<String, Object> toMultimap(
			Iterable<MergedAnnotation<A>> input,Function<Multimap<String, Object>, Multimap<String, Object>> finisher, Adapt... adaptations) {
		
		Multimap<String, Object> result = LinkedHashMultimap.create();
		for(MergedAnnotation<A> ma:input) {
			for(Entry<String, Object> entry:ma.asMap(adaptations).entrySet()) {
				result.put(entry.getKey(), entry.getValue());
			}
		}
		return null == finisher ? result : finisher.apply(result);
	}

}
